package frontend;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.RowFilter;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableRowSorter;

import model.BookMasterTableModel;
import net.miginfocom.swing.MigLayout;
import domain.Book;
import domain.Library;

public class BookMasterJPanel extends JPanel {
    private static final long serialVersionUID = -1761899999291798063L;
    private Library library;
    private JLabel lblNumCopiesValue;
    private JLabel lblNumBooksValue;
    private JButton btnShowSelected;
    private JTable tblBooks;
    private JTextField txtSuche;
    private JCheckBox chckbxNurVerfgbare;
    private TableRowSorter<BookMasterTableModel> sorter;
    ArrayList<RowFilter<Object, Object>> bookTableFilters = new ArrayList<RowFilter<Object, Object>>();
    private JButton btnNeuesBuch;

    /**
     * Create the frame.
     */
    public BookMasterJPanel() {
        this.library = Library.getInstance();

        GridBagLayout gbl_masterPanel = new GridBagLayout();
        gbl_masterPanel.columnWidths = new int[] { 0, 0 };
        gbl_masterPanel.rowHeights = new int[] { 0, 0, 0 };
        gbl_masterPanel.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
        gbl_masterPanel.rowWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
        this.setLayout(gbl_masterPanel);

        JPanel inventoryStatsPanel = new JPanel();
        inventoryStatsPanel.setBorder(BorderFactory.createTitledBorder("Inventar Statistiken"));
        GridBagConstraints gbc_inventoryStatsPanel = new GridBagConstraints();
        gbc_inventoryStatsPanel.insets = new Insets(5, 5, 5, 5);
        gbc_inventoryStatsPanel.fill = GridBagConstraints.BOTH;
        gbc_inventoryStatsPanel.gridx = 0;
        gbc_inventoryStatsPanel.gridy = 0;
        this.add(inventoryStatsPanel, gbc_inventoryStatsPanel);
        inventoryStatsPanel.setLayout(new MigLayout("", "[fill][fill][30px,fill][fill][fill]", "[]"));

        JLabel lblNumBooks = new JLabel("Anzahl B\u00FCcher:");
        inventoryStatsPanel.add(lblNumBooks, "cell 0 0");

        lblNumBooksValue = new JLabel("999");
        inventoryStatsPanel.add(lblNumBooksValue, "cell 1 0");

        JLabel lblNumCopies = new JLabel("Anzahl Exemplare:");
        inventoryStatsPanel.add(lblNumCopies, "cell 3 0");

        lblNumCopiesValue = new JLabel("9999");
        inventoryStatsPanel.add(lblNumCopiesValue, "cell 4 0");

        JPanel inventoryPanel = new JPanel();
        inventoryPanel.setBorder(BorderFactory.createTitledBorder("Buch-Inventar"));
        GridBagConstraints gbc_inventoryPanel = new GridBagConstraints();
        gbc_inventoryPanel.insets = new Insets(5, 5, 5, 5);
        gbc_inventoryPanel.fill = GridBagConstraints.BOTH;
        gbc_inventoryPanel.gridx = 0;
        gbc_inventoryPanel.gridy = 1;
        this.add(inventoryPanel, gbc_inventoryPanel);
        inventoryPanel.setLayout(new MigLayout("", "[300px:n,fill][200:n,grow,fill][fill]", "[fill][grow,fill]"));

        txtSuche = new JTextField();
        txtSuche.setText("Suche");
        inventoryPanel.add(txtSuche, "cell 0 0,growx");
        txtSuche.setColumns(10);

        chckbxNurVerfgbare = new JCheckBox("Nur Verfügbare");
        inventoryPanel.add(chckbxNurVerfgbare, "flowx,cell 1 0");

        btnShowSelected = new JButton("Selektierte Anzeigen");
        btnShowSelected.setEnabled(false);
        inventoryPanel.add(btnShowSelected, "cell 2 0");

        tblBooks = new JTable();
        tblBooks.setModel(BookMasterTableModel.getInstance());
        tblBooks.getColumnModel().getColumn(0).setMinWidth(110);
        tblBooks.getColumnModel().getColumn(0).setMaxWidth(110);
        tblBooks.getColumnModel().getColumn(1).setMinWidth(250);
        sorter = new TableRowSorter<BookMasterTableModel>(BookMasterTableModel.getInstance());
        tblBooks.setRowSorter(sorter);
        inventoryPanel.add(new JScrollPane(tblBooks), "cell 0 1 3 1,grow");

        btnNeuesBuch = new JButton("Neues Buch");
        inventoryPanel.add(btnNeuesBuch, "cell 1 0");

        attachActionListeners();
        updateFromLibrary();
        updateNumSelected();
        setShortcuts();
    }

    private void setShortcuts() {
        chckbxNurVerfgbare.setMnemonic(KeyEvent.VK_V);
        btnShowSelected.setMnemonic('S');
    }

    private void attachActionListeners() {
        tblBooks.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                btnShowSelected.setEnabled(tblBooks.getSelectedRowCount() > 0);
            }
        });
        txtSuche.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                try {
                    sorter.setRowFilter(RowFilter.regexFilter("(?i)" + txtSuche.getText()));
                } catch (Exception ex) {
                    System.out.println("Ungültiger Suchstring eingegeben.");
                }
            }
        });
        btnShowSelected.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showSelectedBook();
            }
        });
        txtSuche.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (txtSuche.getText().equals("Suche")) {
                    txtSuche.setText("");
                }
            }
        });
        txtSuche.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                if (txtSuche.getText().isEmpty()) {
                    txtSuche.setText("Suche");
                }
            }
        });

        chckbxNurVerfgbare.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chckbxNurVerfgbare.isSelected()) {
                    sorter.setRowFilter(RowFilter.regexFilter("^((?!ab).)*$", 0));
                } else {
                    sorter.setRowFilter(null);
                }
            }
        });
        tblBooks.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent arg0) {
                btnShowSelected.setEnabled(tblBooks.getSelectedRowCount() > 0);
            }
        });
        btnNeuesBuch.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                BookDetailJFrame.newBook().setVisible(true);
            }
        });

        Action saveAction = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                showSelectedBook();
            }
        };

        tblBooks.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "save");
        tblBooks.getActionMap().put("save", saveAction);

        tblBooks.addMouseListener(new MouseListener() {
            @Override
            public void mouseReleased(MouseEvent e) {}

            @Override
            public void mousePressed(MouseEvent e) {}

            @Override
            public void mouseExited(MouseEvent e) {}

            @Override
            public void mouseEntered(MouseEvent e) {}

            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() >= 2) {
                    showSelectedBook();
                }
            }
        });
    }

    private void showSelectedBook() {
        Point location = BookMasterJPanel.this.getLocation();
        for (int rowIndex : tblBooks.getSelectedRows()) {
            Book book = BookMasterTableModel.getInstance().getElementAt(tblBooks.convertRowIndexToModel(rowIndex));
            if (BookDetailJFrame.hasInstance(book)) {
                BookDetailJFrame.getInstance(book).toFront();
            } else {
                BookDetailJFrame frame = BookDetailJFrame.getInstance(book);
                if (java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().height < location.y + frame.getSize().height) {
                    location.y = 0;
                }
                frame.setLocation(location.x + 10, location.y + 22);
                location = frame.getLocation();
                frame.setVisible(true);
            }
        }
    }

    public void updateFromLibrary() {
        this.lblNumBooksValue.setText("" + library.getBooks().size());
        this.lblNumCopiesValue.setText("" + library.getCopies().size());
    }

    private void updateNumSelected() {}
}
